"""
命令行接口

提供命令行工具，方便用户使用云盘SDK。
"""

import os
import sys
import click
import json
from typing import Dict, Any, Optional
from pathlib import Path
from .client import CloudSDK
from .models import CloudSDKConfig, ProviderConfig
from .storage import StorageManager, ConfigManager, SessionManager


@click.group()
@click.option('--config-path', default='storage/config.json', help='配置文件路径')
@click.pass_context
def cli(ctx, config_path):
    """云盘统一接入SDK命令行工具"""
    ctx.ensure_object(dict)
    
    # 初始化存储管理器
    base_path = os.path.dirname(config_path) if config_path != 'storage/config.json' else 'storage'
    storage_manager = StorageManager(base_path)
    
    # 初始化配置管理器和会话管理器
    config_manager = ConfigManager(storage_manager)
    session_manager = SessionManager(storage_manager)
    
    # 初始化云盘SDK
    sdk = CloudSDK(config_path=config_path)
    
    # 保存到上下文
    ctx.obj['storage'] = storage_manager
    ctx.obj['config_manager'] = config_manager
    ctx.obj['session_manager'] = session_manager
    ctx.obj['sdk'] = sdk


@cli.command()
@click.option('--type', required=True, help='提供者类型（tianyi_pc, tianyi_tv等）')
@click.option('--name', required=True, help='提供者名称')
@click.option('--config', required=True, help='配置参数（JSON格式）')
@click.pass_context
def add_provider(ctx, type, name, config):
    """添加云盘提供者"""
    config_manager = ctx.obj['config_manager']
    
    try:
        config_dict = json.loads(config)
        provider_config = ProviderConfig(
            type=type,
            name=name,
            enabled=True,
            config=config_dict
        )
        
        if config_manager.add_provider(provider_config):
            click.echo(f"成功添加提供者: {name} ({type})")
        else:
            click.echo(f"添加提供者失败: 可能已存在相同类型的提供者")
    except json.JSONDecodeError:
        click.echo("配置参数格式错误，请使用有效的JSON格式")
    except Exception as e:
        click.echo(f"添加提供者失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.pass_context
def remove_provider(ctx, type):
    """移除云盘提供者"""
    config_manager = ctx.obj['config_manager']
    
    if config_manager.remove_provider(type):
        click.echo(f"成功移除提供者: {type}")
    else:
        click.echo(f"移除提供者失败: 提供者不存在")


@cli.command()
@click.pass_context
def list_providers(ctx):
    """列出所有云盘提供者"""
    config_manager = ctx.obj['config_manager']
    
    providers = config_manager.config.providers
    if not providers:
        click.echo("没有配置任何提供者")
        return
    
    click.echo("已配置的提供者:")
    for provider in providers:
        status = "启用" if provider.enabled else "禁用"
        click.echo(f"  - {provider.name} ({provider.type}) - {status}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.pass_context
def login(ctx, type):
    """登录指定的云盘提供者"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    if provider.login():
        click.echo(f"登录 {type} 成功")
    else:
        click.echo(f"登录 {type} 失败")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.pass_context
def logout(ctx, type):
    """登出指定的云盘提供者"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    if provider.logout():
        click.echo(f"登出 {type} 成功")
    else:
        click.echo(f"登出 {type} 失败")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.pass_context
def status(ctx, type):
    """查看提供者状态"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    # 简单的状态检查
    try:
        # 尝试列出根目录来检查状态
        files = provider.list("/")
        click.echo(f"提供者 {type} 状态: 正常 (根目录有 {len(files)} 个项目)")
    except Exception as e:
        click.echo(f"提供者 {type} 状态: 异常 - {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--path', default='/', help='路径')
@click.option('--recursive', is_flag=True, help='递归列出子目录')
@click.pass_context
def list_files(ctx, type, path, recursive):
    """列出文件和目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        files = provider.list(path, recursive=recursive)
        if not files:
            click.echo("目录为空")
            return
        
        click.echo(f"路径 {path} 的内容:")
        for file in files:
            file_type = "目录" if file.is_dir() else "文件"
            size_info = f" ({file.size} 字节)" if not file.is_dir() else ""
            click.echo(f"  {file_type}: {file.name}{size_info}")
    except Exception as e:
        click.echo(f"列出文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--local-path', required=True, help='本地文件路径')
@click.option('--remote-path', required=True, help='远程文件路径')
@click.option('--rapid-upload', is_flag=True, help='尝试秒传')
@click.pass_context
def upload(ctx, type, local_path, remote_path, rapid_upload):
    """上传文件"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        result = provider.upload(local_path, remote_path, rapid_upload=rapid_upload)
        click.echo(str(result))
    except Exception as e:
        click.echo(f"上传文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--remote-path', required=True, help='远程文件路径')
@click.option('--local-path', required=True, help='本地文件路径')
@click.pass_context
def download(ctx, type, remote_path, local_path):
    """下载文件"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        result = provider.download(remote_path, local_path)
        click.echo(str(result))
    except Exception as e:
        click.echo(f"下载文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--path', required=True, help='文件路径')
@click.pass_context
def delete(ctx, type, path):
    """删除文件或目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    # 确认删除
    if not click.confirm(f"确定要删除 {path} 吗？"):
        click.echo("取消删除")
        return
    
    try:
        if provider.delete(path):
            click.echo(f"删除 {path} 成功")
        else:
            click.echo(f"删除 {path} 失败")
    except Exception as e:
        click.echo(f"删除文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--path', required=True, help='目录路径')
@click.pass_context
def mkdir(ctx, type, path):
    """创建目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        if provider.mkdir(path):
            click.echo(f"创建目录 {path} 成功")
        else:
            click.echo(f"创建目录 {path} 失败")
    except Exception as e:
        click.echo(f"创建目录失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--src-path', required=True, help='源路径')
@click.option('--dst-path', required=True, help='目标路径')
@click.pass_context
def move(ctx, type, src_path, dst_path):
    """移动文件或目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        if provider.move(src_path, dst_path):
            click.echo(f"移动 {src_path} 到 {dst_path} 成功")
        else:
            click.echo(f"移动 {src_path} 到 {dst_path} 失败")
    except Exception as e:
        click.echo(f"移动文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--src-path', required=True, help='源路径')
@click.option('--dst-path', required=True, help='目标路径')
@click.pass_context
def copy(ctx, type, src_path, dst_path):
    """复制文件或目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        if provider.copy(src_path, dst_path):
            click.echo(f"复制 {src_path} 到 {dst_path} 成功")
        else:
            click.echo(f"复制 {src_path} 到 {dst_path} 失败")
    except Exception as e:
        click.echo(f"复制文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--src-path', required=True, help='源路径')
@click.option('--new-name', required=True, help='新名称')
@click.pass_context
def rename(ctx, type, src_path, new_name):
    """重命名文件或目录"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        if provider.rename(src_path, new_name):
            click.echo(f"重命名 {src_path} 为 {new_name} 成功")
        else:
            click.echo(f"重命名 {src_path} 为 {new_name} 失败")
    except Exception as e:
        click.echo(f"重命名文件失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--path', required=True, help='文件路径')
@click.pass_context
def file_info(ctx, type, path):
    """获取文件信息"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        file_info = provider.get_file_info(path)
        if file_info:
            click.echo(f"文件信息:")
            click.echo(f"  名称: {file_info.name}")
            click.echo(f"  ID: {file_info.file_id}")
            click.echo(f"  类型: {'目录' if file_info.is_dir() else '文件'}")
            click.echo(f"  大小: {file_info.size} 字节")
            click.echo(f"  路径: {file_info.path}")
            if file_info.md5:
                click.echo(f"  MD5: {file_info.md5}")
            if file_info.create_time:
                click.echo(f"  创建时间: {file_info.create_time}")
            if file_info.modify_time:
                click.echo(f"  修改时间: {file_info.modify_time}")
        else:
            click.echo(f"文件 {path} 不存在")
    except Exception as e:
        click.echo(f"获取文件信息失败: {e}")


@cli.command()
@click.option('--type', required=True, help='提供者类型')
@click.option('--path', required=True, help='文件路径')
@click.pass_context
def download_url(ctx, type, path):
    """获取文件下载链接"""
    sdk = ctx.obj['sdk']
    
    provider = sdk.get_provider(type)
    if not provider:
        click.echo(f"提供者 {type} 不存在")
        return
    
    try:
        url = provider.get_download_url(path)
        if url:
            click.echo(f"下载链接: {url}")
        else:
            click.echo(f"获取 {path} 的下载链接失败")
    except Exception as e:
        click.echo(f"获取下载链接失败: {e}")


@cli.command()
@click.pass_context
def save_sessions(ctx):
    """保存所有会话"""
    sdk = ctx.obj['sdk']
    
    try:
        results = sdk.save_all_sessions()
        for provider_type, success in results.items():
            status = "成功" if success else "失败"
            click.echo(f"保存 {provider_type} 会话: {status}")
    except Exception as e:
        click.echo(f"保存会话失败: {e}")


@cli.command()
@click.pass_context
def load_sessions(ctx):
    """加载所有会话"""
    sdk = ctx.obj['sdk']
    
    try:
        results = sdk.load_all_sessions()
        for provider_type, success in results.items():
            status = "成功" if success else "失败"
            click.echo(f"加载 {provider_type} 会话: {status}")
    except Exception as e:
        click.echo(f"加载会话失败: {e}")


@cli.command()
@click.option('--type', help='提供者类型，如果未指定则清除所有会话')
@click.pass_context
def clear_sessions(ctx, type):
    """清除会话"""
    session_manager = ctx.obj['session_manager']
    
    try:
        if type:
            if session_manager.delete_session(type):
                click.echo(f"清除 {type} 会话成功")
            else:
                click.echo(f"清除 {type} 会话失败")
        else:
            if session_manager.clear_sessions():
                click.echo("清除所有会话成功")
            else:
                click.echo("清除所有会话失败")
    except Exception as e:
        click.echo(f"清除会话失败: {e}")


@cli.command()
@click.pass_context
def list_sessions(ctx):
    """列出所有会话"""
    session_manager = ctx.obj['session_manager']
    
    try:
        sessions = session_manager.list_sessions()
        if not sessions:
            click.echo("没有保存的会话")
        else:
            click.echo("已保存的会话:")
            for session in sessions:
                click.echo(f"  - {session}")
    except Exception as e:
        click.echo(f"列出会话失败: {e}")


def main():
    """主函数"""
    cli()


if __name__ == '__main__':
    main()